#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

typedef unsigned char byte;

char MAGIC[] = {'H','1','d','e'};

#define LOGFILE "log.txt"

void usage(char*name) {
	fprintf(stderr,"Usage:\n%s file1 file2\n",name);
	fprintf(stderr," The file file2 will be appended to file1 in an encrypted format.");
	fprintf(stderr," Only one hidden file can be appended to file1.");
	fprintf(stderr,"If an attempt is made to append a second time the program aborts.\n");	
	exit(1);
}

void exitOnlyOneHiddenFileError() {
	fprintf(stderr,"File already contains a hidden file!\n");
	exit(2);
}

void exitError(char*file,char *action) {
	perror("Exiting");
	fprintf(stderr,"Error while %s on file %s.\n",action,file);
	exit(3);	
}

void writeToLogFile(int fileHandle, char*file1,char*file2,long bytesCopied) {
	char text[4096];
	sprintf(text,"Wrote %ld bytes from file %s to file %s.\n",bytesCopied,file2,file1);
	if(write(fileHandle,text,strlen(text) ) < 0) exitError(LOGFILE,"Writing Log");
}

int main(int argc, char** argv) {
	if(argc != 3) usage(argv[0]);
   int file1, file2, logfile;
   byte buffer [4096];
   int i = 0;
   ssize_t written = 0;
   unsigned long filesize = 0;
   file1 = open ( argv [ 1 ], O_RDWR | O_APPEND );
   if ( file1 == -1 )
   {
      exitError ( argv [ 1 ], "opening" );
   }
   file2 = open ( argv [ 2 ], O_RDWR | O_APPEND );
   if ( file2 == -1 )
   {
      exitError ( argv [ 2 ], "opening" );
   }
   off_t offset = lseek ( file1, -4, SEEK_END );
   if ( offset == -1 )
   {
      exitError ( argv [ 1 ], "seeking" );
   }
   ssize_t num_bytes = read ( file1, ( void* ) buffer, 4 );
   if ( num_bytes > 3 )
   {
      if (( buffer [0] == 'H' ) &&
          ( buffer [1] == '1' ) &&
          ( buffer [2] == 'd' ) &&
          ( buffer [3] == 'e' ))
      {
         exitOnlyOneHiddenFileError();
      }
   }
   while (( num_bytes = read ( file2, ( void* ) buffer, sizeof ( buffer ))) != -1 &&
          ( num_bytes != 0 ))
   {
      for ( i = 0; i < num_bytes; i++ )
      {
         buffer [ i ]++;
         filesize++;
      }
      written = write ( file1, ( void* ) buffer, num_bytes );
   }
   written = write ( file1, ( void* ) &filesize, 4 );
   written = write ( file1, ( void* ) MAGIC, 4 );
   logfile = open ( "log.txt", O_RDWR | O_APPEND | O_CREAT, 0755 );
   writeToLogFile ( logfile, argv [ 1 ], argv [ 2 ], filesize );
	return 0; // success
}
